portalcache API
技術選定
HonoとCloudflare Workersの組み合わせを選定しました。
VercelやNetlify functionsでも良かったと思いますが、トレンドの技術に触れたいと考え、この選定に至りました。
Cloudflare Workers上でHonoアプリを動作させます。
問題が見えてきた
Cloudflare Workersの無料枠はメモリが1MBに制限されている
portalcache APIはFirebase Functionsなど、別のプラットフォームで動かす
データ構造の都合上、永続化はFirestoreで行うが、firebase関連のnpmパッケージをバンドルした場合に1MBのメモリ制限が不安である
シンプルなKVSを備えており、定期実行を無料で利用できそう
アーキテクチャ
1. portalcrawler
開発者のユーザ名およびパスワードを環境変数として持つCloudflare Workerです。
ポータル上の授業情報を取得していきます。
リクエスト頻度は、Cron TriggerというCloudflare Workersの機能を用いて制御します。
デフォルトでは1分に1つの授業情報を処理します(一日で1440個)。
通常は、Cloudflare KVに授業ページのURL情報を保持しておき、授業コードからURLを参照できるようになっています。
もし対象のURLにリクエストを送付し、302 Foundが返ってきた場合は、次のように分岐します。
もしリダイレクト先がlogin.jspであれば、ログインし、Cloudflare KVに新しいSESSION IDを保持します。
もしリダイレクト先がすべての授業ページであれば、全URLの再取得を実行します。
全URLの取得・Cloudflare KVへの保存
2. portalcache API
portalcrawlerがクロール情報を保存するAPI。
Cloudflare Workersとして動作します。
重要なイベント(e.g. 課題の新規作成)の発生時に、プッシュ通知基盤にプッシュ通知を送る機能も持ちます。
Hono、TypeScriptで実装しました。
データベースとしてD1、ORMにはDrizzleを採用しました。
RDBを使う場合のテーブル設計を大まかに考えて、クエリ数を見積もらないとなんとも言えないか...
科目数について
1年生:142
2年生:153
3年生:146
4年生:134
(大学院は多すぎるのでいったん無視する)
全部で575個。2日間で平均5回は同じ授業を巡回できる計算
Subjectの扱い方
ポイントとなるのは合同開講である。
問題点
合同開講の講義をクロールするのは時間リソースの浪費である。
合同開講の講義情報を別々に保存するのは、空間リソースの浪費である。
アイデア
個々の授業ページで合同開講を発見した場合、当該授業のコードをキー、巡回順において最も早く巡回される合同開講のコードをキー、それに対する合同開講のコードを値としたKVを構築する。
このKVをJointLectureRelationshipsと呼ぶ。
portalcrawlerによるクロール時には、親に対してのみクロールを実施する。
JointLectureRelationshipsに対し当該授業コードで読み取りを試行し、nullが返却されれば親なのでクロールする。
portalcache APIにおけるキャッシュDBへのアクセス時には、アクセス対象が子かどうかを判定し、親に対するアクセスに向き先を変える。
Lectureの扱い方
Lectureは、ポータル内部的には識別子を与えられたエンティティだが、HTML上にはLecture間の識別に使える値が存在しない。
したがって、値が変われば丸ごと別ものと見なさなければならなくなる。
たとえば、Subjectに3つのLectureがあったとする。時刻$ t_1にアクセスしたときと時刻$ t_2にアクセスしたときで、Lectureの数が3つのままであっても内容がすべて変わっていたとしたら、その3つが2つの時刻間で同一であったと証明することはできないだろう。
ユーザに特定のLectureの情報が変更されたことを通知することは、不可能と考えられる。
各Lectureを識別できない以上、次のように取り扱う必要があるだろう。
Subject全体を単一のエンティティとして取り扱う。
Subjectに含まれるLecturesという値オブジェクトに変更が入ったときには、変更があった旨を通知する。
Homeworkの扱い方
Lectureと同様の性質を持つ。
Lectureという値オブジェクトは、Homeworksという値オブジェクトを持つと考えよう。各Homeworkに変更が入ったら、Homeworks自体が別ものに更新されたと見なす。その変更は、Lectureの変更とも見なされる。
Cloudflare KVの名前空間の使用
general
jointLectureRelationships
lectureDetailURLs
将来の展望
まずは、portalcache APIからFirebase messagingを介し、Flutterアプリが課題の作成情報を保存できることを目標とします。